home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-24 | 32.8 KB | 1,319 lines | [TEXT/KAHL] |
- /*
- File: StdPrefsLib.c
-
- Contains: Standard preferences library routines.
-
- Refer to develop Issue 18, "The Right Way to Implement
- Preferences Files", for additional details on this code.
-
- Written by: Gary Woodcock
-
- Copyright: © 1993-94 by Apple Computer, Inc.
-
- Change History (most recent first):
-
- 3/3/94 Version 1.0.
-
- Notes: This code uses Apple's Universal Interfaces for C.
-
- Send bug reports to Gary Woodcock at AOL: gwoodcock
- or Internet: gwoodcock@aol.com.
- */
-
- //-----------------------------------------------------------------------
- // Includes
-
- #include "CompileFlags.h"
-
- #include "StdPrefsLib.h"
- #include "StdPrefsLibPrivate.h"
- #include "DebugUtils.h"
- #include "FSpCompat.h"
- #include "MoreFilesExtras.h"
-
- //-----------------------------------------------------------------------
- // Private constants
-
- enum
- {
- kApplicationMissingMessageStrID = -16397
- };
-
- //-----------------------------------------------------------------------
- // Private prototypes
-
- static OSErr
- GetPrefsDirVRefNumAndDirID (ConstStr31Param folderName,
- Boolean createFolder, short *vRefNum, long *dirID);
-
- static OSErr
- GetPreferencesFileFSSpec (OSType creator, OSType fileType,
- FSSpec *file);
-
- static Boolean
- DirIDInPrefsDir (short vRefNum, long dirID, long prefsDirID);
-
- static short
- FindVRefNum (short fRefNum);
-
- static unsigned long
- GetVolFreeSpace (short vRefNum);
-
- static unsigned long
- GetVAllocationBlockSize (short vRefNum);
-
- static OSErr
- GetDirPathName (short vRefNum, long dirID, Str255 pathName);
-
- static OSErr
- CopyString (ConstStr255Param theSourceStr, Str255 theDestStr);
-
- static OSErr
- CatenateStrings (ConstStr255Param theFirstStr,
- ConstStr255Param theSecondStr, Str255 theCatenatedStr);
-
- static OSErr
- CopyResource (ResType theType, short theID, FSSpec *fileToCopyTo);
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- NewPreferencesFile (OSType creator, OSType fileType,
- ConstStr31Param fileName, ConstStr31Param folderName,
- ConstStr31Param ownerName)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if (fileName != nil)
- {
- long dirID;
- short vRefNum;
-
- // Get the vRefNum and dirID for the folder to put the preferences file in
- result = GetPrefsDirVRefNumAndDirID (folderName, true, &vRefNum, &dirID);
- if (result == noErr)
- {
- short savedResFile = CurResFile();
-
- // Create the file
- HCreateResFile (vRefNum, dirID, fileName);
- result = ResError();
- if (result == noErr)
- {
- FInfo info;
-
- // Set the file type and creator, and lock the name
- result = HGetFInfo (vRefNum, dirID, fileName, &info);
- if (result == noErr)
- {
- info.fdType = fileType;
- info.fdCreator = creator;
- info.fdFlags |= kNameLocked;
- result = HSetFInfo (vRefNum, dirID, fileName, &info);
- if (result == noErr)
- {
- // Should we add an application-missing message string?
- if (ownerName != nil)
- {
- Str255 preamble;
- Str255 postamble;
-
- // Build the application-missing message string
- GetIndString (preamble, kStdPrefsLibStrsID, kPreambleStrID);
- GetIndString (postamble, kStdPrefsLibStrsID, kPostambleStrID);
-
- if ((preamble != nil) && (postamble != nil))
- {
- result = CatenateStrings (preamble, *((Str255 *)ownerName), preamble);
- if (result == noErr)
- {
- result = CatenateStrings (preamble, postamble, preamble);
- if (result == noErr)
- {
- short fRefNum;
-
- // Open the new file
- result = OpenPreferencesFile (creator, fileType, &fRefNum);
- if (result == noErr)
- {
- Handle messageHdl;
-
- // Add the application-missing message string
- PtrToHand ((Ptr)&preamble, &messageHdl, preamble[0] + 1);
- if ((result = MemError()) == noErr)
- {
- short resID = kApplicationMissingMessageStrID;
-
- result = WritePreference (fRefNum, 'STR ', &resID, messageHdl);
- DisposeHandle (messageHdl);
- result = MemError();
- FailMessage (result != noErr, NewPreferencesFile: DisposeHandle failed.);
- }
- else
- {
- DebugMessage (NewPreferencesFile: PtrToHand failed.);
- }
-
- // Close up shop
- result = ClosePreferencesFile (fRefNum);
- }
- }
- }
- }
- else // GetIndString failed
- {
- result = -1L;
- DebugMessage (NewPreferencesFile: GetIndString failed.);
- }
- }
- }
- else // HSetFInfo failed
- {
- DebugMessage (NewPreferencesFile: HSetFInfo failed.);
- }
- }
- else // HGetFInfo failed
- {
- DebugMessage (NewPreferencesFile: HGetFInfo failed.);
- }
- }
- else // HCreateResFile failed
- {
- DebugMessage (NewPreferencesFile: HCreateResFile failed.);
- }
-
- // Restore the resource file
- UseResFile (savedResFile);
- result = ResError();
- FailMessage (result != noErr, NewPreferencesFile: UseResFile failed.);
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (NewPreferencesFile: Bad parameter);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- OpenPreferencesFile (OSType creator, OSType fileType, short *fRefNum)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if (fRefNum != nil)
- {
- FSSpec prefsFSSpec;
- short savedResFile = CurResFile();
-
- // Get the FSSpec for the preferences file
- result = GetPreferencesFileFSSpec (creator, fileType, &prefsFSSpec);
- if (result == noErr)
- {
- // Open it up
-
- short theFRefNum = FSpOpenResFileCompat (&prefsFSSpec, fsRdWrPerm);
-
- result = ResError();
- if (result == noErr)
- {
- *fRefNum = theFRefNum;
-
- // Restore the resource file
- UseResFile (savedResFile);
- result = ResError();
- FailMessage (result != noErr, OpenPreferencesFile: UseResFile failed.);
- }
- else // FSpOpenResFileCompat failed
- {
- DebugMessage (OpenPreferencesFile: FSpOpenResFileCompat failed.);
- }
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (OpenPreferencesFile: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- ClosePreferencesFile (short fRefNum)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if (fRefNum != -1)
- {
- // Close it
- CloseResFile (fRefNum);
- result = ResError();
- FailMessage (result != noErr, ClosePreferencesFile: CloseResFile failed.);
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (ClosePreferencesFile: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- DeletePreferencesFile (OSType creator, OSType fileType)
- {
- FSSpec prefsFSSpec;
- OSErr result;
-
- // Get the preferences file FSSpec
- result = GetPreferencesFileFSSpec (creator, fileType, &prefsFSSpec);
- if (result == noErr)
- {
- // Delete it
- result = FSpDeleteCompat (&prefsFSSpec);
- FailMessage (result != noErr, DeletePreferencesFile: FSpDeleteCompat failed.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- DeletePreferencesFolder (ConstStr31Param folderName)
- {
- OSErr result = noErr;
-
- // Make sure the parameters are valid
- if (folderName != nil)
- {
- long dirID;
- short vRefNum;
-
- // Get the vRefNum and dirID of the preferences folder
- result = GetPrefsDirVRefNumAndDirID (folderName, false, &vRefNum, &dirID);
- if (result == noErr)
- {
- Str255 pathName;
-
- // Get the path to the folder
- result = GetDirPathName (vRefNum, dirID, pathName);
- if (result == noErr)
- {
- // Delete it
- result = DeleteDirectory (vRefNum, dirID, (StringPtr)pathName);
- FailMessage (result != noErr, DeletePreferencesFolder: DeleteDirectory failed.);
- }
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (DeletePreferencesFolder: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal Boolean
- PreferencesFileExists (OSType creator, OSType fileType)
- {
- FSSpec prefsFSSpec;
- OSErr result = noErr;
-
- // If file doesn't exist, fnfErr will be returned
- result = GetPreferencesFileFSSpec (creator, fileType, &prefsFSSpec);
-
- return (result == noErr);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- GetPreferencesFileVersion (short fRefNum, short versID,
- NumVersion *numVersion, short *regionCode,
- ConstStr255Param shortVersionStr, ConstStr255Param longVersionStr)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if ((fRefNum != -1) && ((versID == kVers1) || (versID == kVers2)) &&
- (numVersion != nil) && (regionCode != nil))
- {
- VersRecHndl versHdl;
- short resID = versID;
-
- // Read the version resource
- result = ReadPreference (fRefNum, 'vers', &resID, (Handle *)&versHdl);
- if ((result == noErr) && (versHdl != nil))
- {
- *numVersion = (**versHdl).numericVersion;
- *regionCode = (**versHdl).countryCode;
-
- // Note that the long version string is packed at the end of the
- // short version string - this is the format for the 'vers'
- // resource
- BlockMoveData ((Ptr)((**versHdl).shortVersion), (Ptr)shortVersionStr,
- (**versHdl).shortVersion[0] + 1);
- BlockMoveData ((Ptr)&((**versHdl).shortVersion[shortVersionStr[0] + 1]),
- (Ptr)longVersionStr, (**versHdl).shortVersion[shortVersionStr[0] + 1] + 1);
-
- // Clean up
- DisposeHandle ((Handle) versHdl);
- result = MemError();
- FailMessage (result != noErr, GetPreferencesFileVersion: DisposeHandle failed.);
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (GetPreferencesFileVersion: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- SetPreferencesFileVersion (short fRefNum, short versID,
- NumVersion *numVersion, short regionCode,
- ConstStr255Param shortVersionStr, ConstStr255Param longVersionStr)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if ((fRefNum != -1) && ((versID == kVers1) || (versID == kVers2)) &&
- (numVersion != nil))
- {
- VersRecHndl versHdl = (VersRecHndl) NewHandleClear (sizeof (VersRec));
-
- if (versHdl != nil)
- {
- short resID = versID;
-
- (**versHdl).numericVersion = *numVersion;
- (**versHdl).countryCode = regionCode;
-
- // Note that the long version string is packed at the end of the
- // short version string - this is the format for the 'vers'
- // resource
- BlockMoveData ((Ptr)(shortVersionStr), (Ptr)((**versHdl).shortVersion),
- shortVersionStr[0] + 1);
- BlockMoveData ((Ptr)(longVersionStr),
- (Ptr)&((**versHdl).shortVersion[shortVersionStr[0] + 1]),
- longVersionStr[0] + 1);
-
- // Write the version resource
- result = WritePreference (fRefNum, 'vers', &resID, (Handle) versHdl);
- }
- else // Couldn't get any memory
- {
- result = MemError();
- DebugMessage (SetPreferencesFileVersion: NewHandleClear failed.);
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (SetPreferencesFileVersion: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- ReadPreference (short fRefNum, ResType resourceType, short *resourceID,
- Handle *preference)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if ((fRefNum != -1) && (preference != nil))
- {
- short savedResFile = CurResFile(); // Save off current resource file
-
- // Use this file
- UseResFile (fRefNum);
- result = ResError();
- if (result == noErr)
- {
- // See if the resource is around
- if ((resourceID != nil) && (*resourceID != 0))
- {
- // Get the resource with the specified ID
- *preference = Get1Resource (resourceType, *resourceID);
- }
- else
- {
- // Get the first resource of this type
- *preference = Get1IndResource (resourceType, 1);
- if ((*preference != nil) && (resourceID != nil))
- {
- Str255 dummy1;
- ResType dummy2;
-
- // Get the resource ID
- GetResInfo (*preference, resourceID, &dummy2, dummy1);
- }
- }
-
- // Did we get a resource successfully?
- if (((result = ResError()) == noErr) && (*preference != nil))
- {
- // Detach it
- DetachResource (*preference);
- result = ResError();
- FailMessage (result != noErr, ReadPreference: DetachResource failed.);
- }
- else // Get1Resource failed
- {
- result = resNotFound;
- DebugMessage (ReadPreference: Get1Resource failed.);
- }
-
- // Restore the resource file
- UseResFile (savedResFile);
- result = ResError();
- FailMessage (result != noErr, ReadPreference: UseResFile failed.);
- }
- else // UseResFile failed
- {
- DebugMessage (ReadPreference: UseResFile failed.);
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (ReadPreference: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- WritePreference (short fRefNum, ResType resourceType, short *resourceID,
- Handle preference)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if ((fRefNum != -1) && (preference != nil))
- {
- Handle localPref = preference;
-
- // Make a local copy of this preference
- result = HandToHand (&localPref);
-
- if (result == noErr)
- {
- Handle oldPref = nil;
- Size prefSize = GetHandleSize (localPref); // Get size of preference to be added
- Size existingPrefSize = prefSize;
- long freeSpaceOnDisk;
- short vRefNum = FindVRefNum (fRefNum);
- short savedResFile = CurResFile(); // Save off current resource file
- short resID;
-
- // Get free disk space
- freeSpaceOnDisk = GetVolFreeSpace (vRefNum);
-
- // Use this file
- UseResFile (fRefNum);
- result = ResError();
- if (result == noErr)
- {
- // See if this resource is already around
- if ((resourceID != nil) && (*resourceID != 0))
- {
- // Get the resource with the specified ID
- oldPref = Get1Resource (resourceType, *resourceID);
- }
-
- // Did we find an existing resource?
- if (oldPref != nil)
- {
- // How big is it?
- existingPrefSize = GetHandleSize (oldPref);
-
- // Make sure that there's enough disk space available to
- // accomodate the resource that's replacing the old one -
- // if there's not, leave the old one in place, and return an error
- // We'll leave at least one allocation block left for the system
- if ((prefSize > existingPrefSize) &&
- (prefSize + GetVAllocationBlockSize (FindVRefNum (fRefNum)) > freeSpaceOnDisk))
- {
- result = dskFulErr;
- DebugMessage (WritePreference: Not enough disk space to write resource.);
- }
- else
- {
- // Get rid of it
- RmveResource (oldPref);
- if ((result = ResError()) == noErr)
- {
- // Update the file
- UpdateResFile (fRefNum);
- result = ResError();
- FailMessage (result != noErr, WritePreference: UpdateResFile failed.);
- }
- else // RmveResource failed
- {
- DebugMessage (WritePreference: RmveResource failed.);
- }
-
- // Clean up
- DisposeHandle (oldPref);
- result = MemError();
- FailMessage (result != noErr, WritePreference: DisposeHandle failed.);
- }
- }
-
- if (result == noErr)
- {
- // Make sure there's room
- if (prefSize + GetVAllocationBlockSize (FindVRefNum (fRefNum)) > freeSpaceOnDisk)
- {
- result = dskFulErr;
- DebugMessage (WritePreference: Not enough disk space to write resource.);
- }
- else
- {
- // Figure out the resource ID to use
- if (resourceID != nil)
- {
- if (*resourceID == 0)
- {
- // Get a unique resource ID
- resID = Unique1ID (resourceType);
- *resourceID = resID;
- }
- else
- {
- resID = *resourceID;
- }
- }
- else
- {
- // Get a unique resource ID
- resID = Unique1ID (resourceType);
- }
-
- // Add the resource
- AddResource (localPref, resourceType, resID, "\p");
- if ((result = ResError()) == noErr)
- {
- // Write it to the file
- WriteResource (localPref);
- FailMessage ((result = ResError()) != noErr, WritePreference:
- WriteResource failed.);
-
- // Clean up
- ReleaseResource (localPref);
- FailMessage ((result = ResError()) != noErr, WritePreference:
- ReleaseResource failed.);
- }
- else // AddResource failed
- {
- DebugMessage (WritePreference: AddResource failed.);
- }
- }
- }
-
- // Restore the resource file
- UseResFile (savedResFile);
- result = ResError();
- FailMessage (result != noErr, WritePreference: UseResFile failed.);
- }
- else // UseResFile failed
- {
- DebugMessage (WritePreference: UseResFile failed.);
- }
- }
- else // HandToHand failed
- {
- DebugMessage (WritePreference: HandToHand failed.);
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (WritePreference: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- pascal OSErr
- DeletePreference (short fRefNum, ResType resourceType, short resourceID)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if (fRefNum != -1)
- {
- Handle prefToKill;
- short savedResFile = CurResFile(); // Save off the current resource file
-
- // Use this file
- UseResFile (fRefNum);
- result = ResError();
- if (result == noErr)
- {
- // Are there any of these resources around?
- if (Count1Resources (resourceType) > 0)
- {
- // See if this resource is around
- if (resourceID != 0)
- {
- // Get the resource with the specified ID
- prefToKill = Get1Resource (resourceType, resourceID);
- }
- else
- {
- // Get the first resource of this type
- prefToKill = Get1IndResource (resourceType, 1);
- }
-
- // Did we find a resource to delete?
- if (prefToKill != nil)
- {
- // Remove it
- RmveResource (prefToKill);
- if ((result = ResError()) == noErr)
- {
- // Update the file
- UpdateResFile (fRefNum);
- FailMessage ((result = ResError()) != noErr, DeletePreference:
- UpdateResFile failed.);
- }
- else // RmveResource failed
- {
- DebugMessage (DeletePreference: RmveResource failed.);
- }
-
- // Clean up
- DisposeHandle (prefToKill);
- result = MemError();
- FailMessage (result != noErr, DeletePreference: DisposeHandle failed.);
- }
- }
- else // Couldn't find this resource
- {
- result = resNotFound;
- DebugMessage (DeletePreference: Resource not found.);
- }
-
- // Restore the resource file
- UseResFile (savedResFile);
- result = ResError();
- FailMessage (result != noErr, DeletePreference: UseResFile failed.);
- }
- else // UseResFile failed
- {
- DebugMessage (DeletePreference: UseResFile failed.);
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (DeletePreference: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- static OSErr
- GetPrefsDirVRefNumAndDirID (ConstStr31Param folderName,
- Boolean createFolder, short *vRefNum, long *dirID)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if ((vRefNum != nil) && (dirID != nil))
- {
- long id;
-
- // Locate the Preferences folder
- result = FindFolder (kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
- vRefNum, &id);
- if (result == fnfErr)
- {
- // No Preferences folder found, try to find the System Folder
- result = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
- vRefNum, &id);
- if (result != noErr)
- {
- // Couldn't find the System Folder - we're hosed
- DebugMessage (GetPrefsDirVRefNumAndDirID: FindFolder failed.);
- goto BAIL;
- }
- }
- else if (result != noErr)
- {
- // Got some other kind of bad error from FindFolder when trying
- // to find the Preferences folder
- DebugMessage (GetPrefsDirVRefNumAndDirID: FindFolder failed.);
- goto BAIL;
- }
-
- // Are we using a custom preferences folder?
- if (folderName != nil)
- {
- DirInfo info;
-
- // See if the specified custom preferences folder is around
- info.ioNamePtr = (StringPtr) folderName;
- info.ioVRefNum = *vRefNum;
- info.ioDrDirID = id;
- info.ioFDirIndex = 0;
- result = PBGetCatInfo ((CInfoPBPtr)&info, false);
- if (result == noErr)
- {
- *dirID = info.ioDrDirID;
- }
- else if ((result == fnfErr) && createFolder)
- {
- // Try to create the specified custom preferences folder
- result = DirCreate (*vRefNum, id, folderName, dirID);
- FailMessage (result != noErr, GetPrefsDirVRefNumAndDirID: DirCreate failed.);
- }
- else // PBGetCatInfo failed
- {
- DebugMessage (GetPrefsDirVRefNumAndDirID: PBGetCatInfo failed.);
- }
- }
- else // Not using a custom preferences folder
- {
- *dirID = id;
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (GetPrefsDirVRefNumAndDirID: Bad parameter.);
- }
-
- BAIL:
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- static OSErr
- GetPreferencesFileFSSpec (OSType creator, OSType fileType,
- FSSpec *file)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if (file != nil)
- {
- long systemFolderDirID;
- long prefsFolderDirID;
- short vRefNum;
- Boolean hasPrefsDir;
- Boolean foundIt = false;
-
- // Find the Preferences folder dirID
- result = FindFolder (kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
- &vRefNum, &prefsFolderDirID);
- hasPrefsDir = (result == noErr);
-
- // Find the System Folder dirID
- result = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
- &vRefNum, &systemFolderDirID);
-
- // Did we find the System Folder OK?
- if (result == noErr)
- {
- FSSpec possibleMatch;
- long numMatches;
- Boolean firstSearch = true;
-
- // Check the Preferences folder first
- if (hasPrefsDir)
- {
- // Loop through the possible candidates until a candidate is found
- do
- {
- result = CreatorTypeFileSearch (nil, vRefNum, creator, fileType,
- (FSSpecPtr) &possibleMatch, 1L, &numMatches, firstSearch);
-
- firstSearch = false;
-
- // Did we get a match?
- if (numMatches == 1)
- {
- // Check to see if this file is within the Preferences
- // folder or any of its nested folders
- if (DirIDInPrefsDir (vRefNum, possibleMatch.parID, prefsFolderDirID))
- {
- // Got one!
- foundIt = true;
- break;
- }
- }
- }
- while ((result == noErr) || (result == catChangedErr));
- }
-
- // If we didn't find it in the Preferences folder, check the
- // System Folder
- if (!foundIt)
- {
- // Loop through the possible candidates until a candidate is found
- firstSearch = true;
- do
- {
- result = CreatorTypeFileSearch (nil, vRefNum, creator, fileType,
- (FSSpecPtr) &possibleMatch, 1L, &numMatches, firstSearch);
-
- firstSearch = false;
-
- // Did we get a match?
- if ((numMatches == 1) && (possibleMatch.parID == systemFolderDirID))
- {
- // Got one!
- foundIt = true;
- break;
- }
- }
- while ((result == noErr) || (result == catChangedErr));
- }
-
- // If we found one, return it
- if (foundIt)
- {
- *file = possibleMatch;
- }
- else // Didn't find a preferences file with the specified creator and file type
- {
- result = fnfErr;
- DebugMessage (GetPreferencesFileFSSpec: Could not find preferences file.);
- }
- }
- else // Couldn't find the System Folder
- {
- DebugMessage (GetPreferencesFileFSSpec: FindFolder failed.);
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (GetPreferencesFileFSSpec: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- static Boolean
- DirIDInPrefsDir (short vRefNum, long dirID, long prefsDirID)
- {
- OSErr result = noErr;
- Boolean inPrefsDir = false;
-
- // Make sure parameters are valid
- if (vRefNum < 0)
- {
- // Is the dirID of the directory the same as the Preferences
- // folder dirID?
- if (dirID == prefsDirID)
- {
- inPrefsDir = true;
- }
- else // Nope, we need to follow the path up toward the root
- {
- DirInfo info;
- Str255 dirName;
- Str255 pathName;
-
- // Initialize some stuff
-
- pathName[0] = '\0';
-
- info.ioDrParID = dirID;
- info.ioNamePtr = dirName;
-
- // Walk the path upward, one directory at a time,
- // until we either determine that the directory is
- // in the Preferences folder, or until we hit the
- // root directory (this always has a dirID of 2)
- do
- {
- info.ioVRefNum = vRefNum;
- info.ioFDirIndex = -1;
- info.ioDrDirID = info.ioDrParID;
- result = PBGetCatInfo ((CInfoPBPtr)&info, false);
- if (result == noErr)
- {
- // Is this the Preferences folder?
- if (info.ioDrParID == prefsDirID)
- {
- // Yep, we can leave now
- inPrefsDir = true;
- break;
- }
- else // Nope, append this string to the path name and try again
- {
- result = CatenateStrings (dirName, "\p:", dirName);
- if (result == noErr)
- {
- result = CatenateStrings (dirName, pathName, pathName);
- if (result != noErr)
- {
- // CatenateStrings failed
- break;
- }
- }
- else // CatenateStrings failed
- {
- break;
- }
- }
- }
- else // PBGetCatInfo failed
- {
- DebugMessage (DirIDInPrefsDir: PBGetCatInfo failed.);
- break;
- }
- }
- while (info.ioDrDirID != 2);
- }
- }
- else // Bad parameter
- {
- DebugMessage (DirIDInPrefsDir: Bad parameter.);
- }
- return (inPrefsDir);
- }
-
- //-----------------------------------------------------------------------
-
- static short
- FindVRefNum (short fRefNum)
- {
- OSErr result = noErr;
- short vRefNum = 0;
-
- // Make sure parameters are valid
- if (fRefNum != -1)
- {
- FCBPBRec fcbInfo;
- Str63 fName;
-
- // Set up parameter block
- fcbInfo.ioNamePtr = fName;
- fcbInfo.ioVRefNum = 0;
- fcbInfo.ioRefNum = fRefNum;
- fcbInfo.ioFCBIndx = 0;
- result = PBGetFCBInfoSync (&fcbInfo);
- if (result == noErr)
- {
- vRefNum = fcbInfo.ioFCBVRefNum;
- }
- else // PBGetFCBInfoSync failed
- {
- DebugMessage (FindVRefNum: PBGetFCBInfoSync failed.);
- }
- }
- else // Bad parameter
- {
- DebugMessage (FindVRefNum: Bad parameter.);
- }
- return (vRefNum);
- }
-
- //-----------------------------------------------------------------------
-
- static unsigned long
- GetVolFreeSpace (short vRefNum)
- {
- HParamBlockRec pb;
- OSErr result = noErr;
-
- pb.volumeParam.ioNamePtr = nil; // We don't care about the name
- pb.volumeParam.ioVRefNum = vRefNum;
- pb.volumeParam.ioVolIndex = 0; // Use ioVRefNum only
- result = PBHGetVInfo (&pb, false);
-
- if (result == noErr)
- {
- // Calculate the free space in bytes
- return (pb.volumeParam.ioVFrBlk * pb.volumeParam.ioVAlBlkSiz);
- }
- else // PBHGetVInfo failed
- {
- DebugMessage (GetVolFreeSpace: PBHGetVInfo failed.);
- return (0L);
- }
- }
-
- //-----------------------------------------------------------------------
-
- static unsigned long
- GetVAllocationBlockSize (short vRefNum)
- {
- HParamBlockRec pb;
- OSErr result = noErr;
-
- pb.volumeParam.ioNamePtr = nil; // We don't care about the name
- pb.volumeParam.ioVRefNum = vRefNum;
- pb.volumeParam.ioVolIndex = 0; // Use ioVRefNum only
- result = PBHGetVInfo (&pb, false);
-
- if (result == noErr)
- {
- return (pb.volumeParam.ioVAlBlkSiz);
- }
- else
- {
- return (0L);
- }
- }
-
- //-----------------------------------------------------------------------
-
- static OSErr
- GetDirPathName (short vRefNum, long dirID, Str255 pathName)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if (vRefNum < 0)
- {
- DirInfo info;
- Str255 dirName;
-
- // Initialize some stuff
-
- pathName[0] = '\0';
-
- info.ioDrParID = dirID;
- info.ioNamePtr = dirName;
-
- // Walk the path upward, one directory at a time,
- // until we hit the root directory (this always
- // has a dirID of 2)
- do
- {
- info.ioVRefNum = vRefNum;
- info.ioFDirIndex = -1;
- info.ioDrDirID = info.ioDrParID;
- result = PBGetCatInfo ((CInfoPBPtr)&info, false);
- if (result == noErr)
- {
- result = CatenateStrings (dirName, "\p:", dirName);
- if (result == noErr)
- {
- result = CatenateStrings (dirName, pathName, pathName);
- if (result != noErr)
- {
- // CatenateStrings failed
- break;
- }
- }
- else // CatenateStrings failed
- {
- break;
- }
- }
- else // PBGetCatInfo failed
- {
- DebugMessage (GetDirPathName: PBGetCatInfo failed.);
- break;
- }
- }
- while (info.ioDrDirID != 2);
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (GetDirPathName: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- static OSErr
- CopyString (ConstStr255Param theSourceStr, Str255 theDestStr)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if ((theSourceStr != nil) && (theDestStr != nil))
- {
- BlockMoveData ((Ptr)theSourceStr, (Ptr)theDestStr, theSourceStr[0] + 1);
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (StrCopy: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- static OSErr
- CatenateStrings (ConstStr255Param theFirstStr,
- ConstStr255Param theSecondStr, Str255 theCatenatedStr)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if ((theFirstStr != nil) && (theSecondStr != nil) &&
- (theCatenatedStr != nil))
- {
- Str255 catenatedStr;
- Str255 secondStr;
- long tempSize;
- short combinedLength = theFirstStr[0] + theSecondStr[0];
- short secondStrLength = theSecondStr[0];
-
- // Can both strings fit in a Str255?
- if (combinedLength > 255)
- {
- // Nope, let's shorten the second string to fit
- secondStrLength = 255 - theFirstStr[0];
- }
-
- // Copy the strings
- BlockMoveData ((Ptr)theFirstStr, (Ptr)catenatedStr, theFirstStr[0] + 1);
- BlockMoveData ((Ptr)theSecondStr, (Ptr)secondStr, secondStrLength + 1);
-
- // Copy the second string to the end of the first string
- tempSize = catenatedStr[0];
- catenatedStr[0] += secondStr[0];
- BlockMoveData ((Ptr)&secondStr[1], (Ptr)&catenatedStr[tempSize + 1],
- secondStr[0]);
-
- // Copy the catenated string back out
- BlockMoveData ((Ptr)catenatedStr, (Ptr)theCatenatedStr,
- catenatedStr[0] + 1);
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (StrCatenate: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
- static OSErr
- CopyResource (ResType theType, short theID, FSSpec *fileToCopyTo)
- {
- OSErr result = noErr;
-
- // Make sure parameters are valid
- if (fileToCopyTo != nil)
- {
- Handle resToBeCopied = GetResource (theType, theID);
- short appResRefNum;
-
- if ((result = ResError()) == noErr)
- {
- // Get the application's resource refNum
- appResRefNum = LMGetCurApRefNum();
- if ((resToBeCopied != nil) &&
- (appResRefNum == HomeResFile (resToBeCopied)))
- {
- Handle resToCopyTo;
- short resAttributes;
- short copyToFileResRefNum;
- short savedResFile = CurResFile();
-
- // Get the attributes of the resource to be copied
- resAttributes = GetResAttrs (resToBeCopied);
-
- // Detach the resource to be coped
- DetachResource (resToBeCopied);
- if ((result = ResError()) == noErr)
- {
- // Open the file to copy to
- copyToFileResRefNum = FSpOpenResFile (fileToCopyTo, fsRdWrPerm);
- if ((result = ResError()) == noErr)
- {
- // Set the resource refNum
- UseResFile (copyToFileResRefNum);
-
- // Check for existing resources with this type and ID in
- // the file we're copying to, and remove any we find
- do
- {
- // Get a resource
- resToCopyTo = GetResource (theType, theID);
-
- // Is the resource's res file the same as the
- // file we're trying to copy to?
- if (HomeResFile (resToCopyTo) == copyToFileResRefNum)
- {
- // Remove it
- RmveResource (resToCopyTo);
- FailMessage ((result = ResError()) != noErr, CopyResource: RmveResource failed.);
- DisposeHandle (resToCopyTo);
- FailMessage ((result = MemError()) != noErr, CopyResource: DisposeHandle failed.);
- }
- }
- while (HomeResFile (resToCopyTo) != copyToFileResRefNum);
-
- // Add the resource
- AddResource (resToBeCopied, theType, theID, "\p");
- if ((result = ResError()) == noErr)
- {
- // Set up the resource's attributes
- SetResAttrs (resToBeCopied, resAttributes);
- ChangedResource (resToBeCopied);
- FailMessage ((result = ResError()) != noErr, CopyResource: ChangedResource failed.);
- }
-
- // Close the file
- CloseResFile (copyToFileResRefNum);
-
- // Restore resource file
- UseResFile (savedResFile);
- }
- else // FSpOpenResFile failed
- {
- DebugMessage (CopyResource: FSpOpenResFile failed.);
- }
- }
- else // DetachResource failed
- {
- DebugMessage (CopyResource: DetachResource failed.);
- }
- }
- }
- else // GetResource failed
- {
- DebugMessage (CopyResource: GetResource failed.);
- }
- }
- else // Bad parameter
- {
- result = paramErr;
- DebugMessage (CopyResource: Bad parameter.);
- }
- return (result);
- }
-
- //-----------------------------------------------------------------------
-
-
-
-